import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.List;
import java.awt.Menu;
import java.awt.MenuBar;
import java.awt.MenuItem;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.util.ArrayList;
import java.util.concurrent.CountDownLatch;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;

public class ClientUi implements ActionListener {
	final CountDownLatch sendEnd;
	
	ClientUi clientUi = this;
	JFrame fenetre;
	JPanel paneScore;
	JLabel labScore;
	JLabel labWin;
	JPanel paneInfo;
	JLabel failLeft;
	JLabel chainWord;
	JPanel paneGuess;
	JLabel labGuess;
	JPanel paneError;
	JLabel labError;
	JTextField textGuess;
	JButton btnSend;
	Client client;
	MenuItem startItemMenu;
	MenuItem closeItemMenu;
	Boolean start = false;
	private java.util.List<String> sendCharacters;
	JLabel sendCharactersLabel;
	JPanel sendCharacPanel;

	public ClientUi(Client client) {
		
		sendCharacters = new ArrayList<String>();
		sendEnd = new CountDownLatch(1);
		this.client = client;
		this.fenetre = new JFrame();
		this.fenetre.setTitle("Client Hangman");
		this.fenetre.setSize(400, 500);
		// Place the window in the center of the screen
		this.fenetre.setLocationRelativeTo(null);
		this.fenetre.setLayout(new GridLayout(5,1));

	
		/* ***************************************************************
		 * ******************  Manage Score panel  ************************
		 * ***************************************************************
		 */
		paneScore = new JPanel();
		paneScore.setLayout(new GridLayout(2, 1));
		labScore = new JLabel("Score client : 0");
		labWin = new JLabel("");
		
		paneScore.add(labScore);
		paneScore.add(labWin);
		
		/* **************************************************************
		 * ************ Manage panel info **************
		 * ************************************************************
		 */
		paneInfo = new JPanel(new BorderLayout());
		paneInfo.setPreferredSize(new Dimension(this.fenetre.getWidth(), 50));
		chainWord = new JLabel("to start click Menu/start");
		chainWord.setHorizontalAlignment(JLabel.CENTER);
		failLeft = new JLabel("You still have X attempt left");
		failLeft.setHorizontalAlignment(JLabel.CENTER);

		paneInfo.add(chainWord,BorderLayout.NORTH);
		paneInfo.add(failLeft,BorderLayout.SOUTH);

		/* **************************************************************
		 * ************ Manage panel guess **************
		 * ************************************************************
		 */
		paneGuess = new JPanel();
		labGuess = new JLabel("Letter or word :");
		textGuess = new JTextField();
		Dimension dim = new Dimension(100, 20);
		textGuess.setPreferredSize(dim);

		paneGuess.add(labGuess);
		paneGuess.add(textGuess);
		
		/* **************************************************************
		 * ************ send characters panel  **************
		 * ************************************************************
		 */
		sendCharacPanel = new JPanel();
		JLabel phraseSendCharacters = new JLabel("You tried these letters: ");
		sendCharactersLabel = new JLabel();
		
		
		sendCharacPanel.add(phraseSendCharacters);
		sendCharacPanel.add(sendCharactersLabel);
		/* ***************************************************************
		 * ******************  Manage error Pane  ************************
		 * ***************************************************************
		 */
		paneError = new JPanel();
		labError = new JLabel("");
		
		paneError.add(labError);
		
		
		/*****************************************************************
		 * *************** Manage button *********************************
		 * *************************************************************
		 */
		btnSend = new JButton("Send");
		btnSend.setEnabled(false);
		MenuBar menuBar = new MenuBar();
		Menu menu = new Menu("Menu");
		startItemMenu = new MenuItem("start");
		closeItemMenu = new MenuItem("close/end");

		menuBar.add(menu);
		menu.add(startItemMenu);
		menu.add(closeItemMenu);
		fenetre.setMenuBar(menuBar);

		startItemMenu.addActionListener(this);
		closeItemMenu.addActionListener(this);
		btnSend.addActionListener(this);
		/* ******************************************************************************
		 * ************    Window and Keyboard Listener         *************************
		 * ******************************************************************************
		 */
		WindowListener listener = new WindowAdapter() {
		      public void windowClosing(WindowEvent w) {
		        close();
		      }
		};
		
		fenetre.addWindowListener(listener);
		KeyListener keyListener = new KeyAdapter(){
			public void keyPressed( KeyEvent e){
				if( (e.getExtendedKeyCode() == KeyEvent.VK_ENTER) && start ){
					sendGuess();
				}
			}
		};
		textGuess.addKeyListener(keyListener);
		
		paneGuess.add(btnSend);

		this.fenetre.getContentPane().add(this.paneScore);
		this.fenetre.getContentPane().add(this.paneInfo);
		this.fenetre.getContentPane().add(this.paneGuess);
		this.fenetre.getContentPane().add(this.sendCharacPanel);
		this.fenetre.getContentPane().add(this.paneError);
		fenetre.pack();
		this.fenetre.setVisible(true);
		
	}

	@Override
	public synchronized void actionPerformed(ActionEvent arg0) {
		System.out.println("Event occur");
		
		if (arg0.getSource() == startItemMenu) {
			sendCharacters.clear();
			sendCharactersLabel.setText("");
			startRequest();
			
		}
		if (arg0.getSource() == closeItemMenu) {
			close();
		}
		if (arg0.getSource() == btnSend) {
			this.sendGuess();
		}
	}
	
	private void populateSendCharactersPanel(){
		StringBuilder strb = new StringBuilder();
		for (String str : sendCharacters) {
			strb.append(" "+str);
		}
		sendCharactersLabel.setText(strb.toString());
	}
	/**
	 * Function to call before closing the UI, it will send a stop game message to the server
	 * and close socket
	 */
	public void close(){
		try {
			System.out.println("Close the game");
			
			Message msg = new Message(Message.STOP_GAME);
			Thread t = new Thread(new Communication(this, client, msg));
			t.start();

			sendEnd.await();
			System.out.println("Ask to close socket");
			client.close();
			System.out.println("Socket closed");
			System.exit(0);
			
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	/**
	 * Function send a guess message ( letter or word) to the server
	 */
	public void sendGuess(){
		String str = textGuess.getText();
		if(str.length() <= 1 && !sendCharacters.contains(str)){
			sendCharacters.add(str);
			populateSendCharactersPanel();
		}
		//create a new message for the server
		Message msg = new Message(Message.CLIENT_SERVER);
		msg.setArg(textGuess.getText());
		textGuess.setText(null);
		//create a new thread to handle the message
		Thread t = new Thread(new Communication(this, client, msg));
		t.start();
	}
	/**
	 * Function to call to start the game or check for a new word
	 */
	public void startRequest(){
		System.out.println("Start game");
		labWin.setText("");
		start = true;
		Message msg = new Message(Message.START_GAME);
		btnSend.setEnabled(true);
		Thread t = new Thread(new Communication(this, client, msg));
		t.start();
	}
	
	public void windowClosed(WindowEvent e) {
		close();
	}
}
